package com.itheima.extendsconstructor;

public class Student {

    private String name;
    private int age;
    private String gender;

    public Student() {
    }

    public Student(String name, int age) {
        /*this.name = name;
        this.age = age;
        this.gender = "男";*/

        //this(...)调用兄弟构造器（同一个类中的其他构造器）
        this(name, age, "男");

        //注意：super(...)和this(...)都必须放在第一行，
        // 且两者不能同时出现（同时出现会导致重复初始化）

        /*
        在Java中，`super()`语句用于调用父类的构造器。它必须放在子类构造器的第一行，
        这是因为Java虚拟机（JVM）需要确保在子类执行任何代码之前，其直接超类的构造器已经被调用并完成了对象的初始化。
        这是对象构造过程中的一个关键步骤，以确保对象状态的正确性和完整性。

        具体来说，当创建一个对象时，JVM会按照以下顺序执行构造过程：
        1. 分配内存空间给新对象。
        2. 调用直接超类的无参数构造器（如果没有显式调用其他构造器的话）。
        3. 初始化成员变量为它们的默认值或显式给出的初始值。
        4. 执行子类构造器体内的代码。

        如果`super()`不在子类构造器的第一行，那么在`super()`被执行前，
        子类构造器的其他代码可能会尝试访问或修改尚未被完全初始化的成员变量，
        这可能导致程序行为的不确定性或错误。因此，为了保证对象构造的正确性，
        Java语言规范要求`super()`必须是子类构造器的第一个语句。
        如果子类构造器没有显式地调用`super()`，则会默认调用超类的无参数构造器。
         */

        /*
        在Java中，`this()`表达式用于在一个类的构造器中调用该类的另一个构造器。
        这个调用必须放在构造器的第一行，原因与`super()`调用父类构造器相似，
        但涉及的是同一类中的不同构造器之间的调用。

        当一个构造器通过`this()`调用另一个构造器时，它实际上是在执行以下操作：
        1. 使用`this()`指定的构造器来初始化对象的状态。
        2. 确保在执行任何其他初始化代码之前，对象的基本状态已经被正确初始化。

        将`this()`放在构造器的第一行，可以确保：
        - 对象的初始化逻辑清晰且一致。
        - 在构造器执行任何其他代码之前，对象已经处于一个稳定的状态。
        - 避免在对象尚未完成初始化的情况下就访问或修改其成员变量，这可能引发未定义的行为或错误。

        如果不把`this()`放在构造器的第一行，
        那么在调用`this()`之前执行的任何代码都可能尝试访问或修改尚未初始化的成员变量，
        导致程序状态的混乱。因此，Java语言规范要求，
        如果在构造器中使用了`this()`或`super()`来调用其他构造器，它们必须是构造器体内的第一个语句。
        这样可以确保构造器的调用顺序和对象初始化的一致性和安全性。
         */
    }

    public Student(String name, int age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}
